Skip to main content

Operator Overloads

The principle of encapsulation is one of the most important notions in object-oriented design. This principle states that data stored inside an object should be accessible only to that object.

Operator overloads allow framework types to appear as if they were built-in language primitives.

Although allowed and useful in some situations, operator overloads should be used cautiously. There are many cases in which operator overloading has been abused, such as when framework designers started to use operators for operations that should be simple methods.

The following guidelines should help you decide when and how to use operator overloading.

❌ AVOID defining operator overloads, except in types that should feel like primitive (built-in) types.

✔️ CONSIDER defining operator overloads in a type that should feel like a primitive type.

For example, xtd:ustring has operator == and operator != defined.

✔️ DO define operator overloads in structs that represent numbers.

❌ DO NOT be cute when defining operator overloads.

Operator overloading is useful in cases in which it is immediately obvious what the result of the operation will be. For example, it makes sense to be able to subtract one date_time from another date_time and get a time_span. However, it is not appropriate to use the logical union operator to union two database queries, or to use the shift operator to write to a stream.

❌ DO NOT provide operator overloads unless at least one of the operands is of the type defining the overload.

✔️ DO overload operators in a symmetric fashion.

For example, if you overload the operator ==, you should also overload the operator !=. Similarly, if you overload the operator <, you should also overload the operator >, and so on.

✔️ CONSIDER providing methods with friendly names that correspond to each overloaded operator.

xtd::iequatable

The xtd::iequatable<type_t> interface class implement the == and != operators and used the virtual bool equals(const type_t&) const noexcept; method. You must just overload this method for used your own implementation.

The point class show how to used equals method :

class point : public xtd::object, public xtd::iequatable<point> {
//...

public:
bool equals(const point& value) const noexcept override {
return x_ == value.x_ && y_ == value.y_;
}

//...

private:
int x_ = 0;
int y_ = 0;
};

//...

static ustring form1::check_points(const point& p1, const point& p2) {
if (p1 == p2) eturn "Equals";
return "Not equals";
}

xtd::icomparable

The xtd::icomparable<type_t> interface implement the <, <=, > and >= operators. and used the virtual int compare_to(const type_t&) const noexcept; method. You must just overload this method for used your own implementation.

The time_span class show how to used compare_to method:

class time_span : public xtd::object, public xtd::icomparable<time_span> {
//...

public:
int compare_to(const time_span& value) const noexcept override {
return value_ < value.value_ ? -1 : value_ > value.value_ ? 1 : 0;
}

//...

private:
int64 value_ = 0;
};

//...

time_span test::get_max_duration(const std::vector<time_span>& durations) const noexcept {
time_span result;
for (const auto& duration : durations)
if (duration > result) result = duration;
return result;
}

Operator in C++

This is a list of operators in the C++ programming languages. All the operators listed exist in C++.

When not overloaded, for the operators &&, ||, and , (the comma operator), there is a sequence point after the evaluation of the first operand.

C++ also contains the type conversion operators const_cast, static_cast, dynamic_cast, and reinterpret_cast. The formatting of these operators means that their precedence level is unimportant.

For the purposes of this tables, a, b, and c represent valid values (literals, values from variables, or return value), object names, or lvalues, as appropriate. R, S and T stand for any type(s), and K for a class type or enumerated type.

"Can overload" means that the operator can be overloaded in C++.

Arithmetic operators

 Operator nameSyntaxCan overloadPrototype examples as member of KProtype examples outside class definition
Basic assignmenta = bYesR& K::operator =(S b);N/A
Additiona + bYesR K::operator +(S b);R operator +(K a, S b);
Subtractiona - bYesR K::operator -(S b);R operator -(K a, S b);
Unary plus (integer promotion)+aYesR K::operator +();R operator +(K a);
Unary minus (additive inverse)-aYesR K::operator -();R operator -(K a);
Multiplicationa * bYesR K::operator *(S b);R operator *(K a, S b);
Divisiona / bYesR K::operator /(S b);R operator /(K a, S b);
Modulo (integer remainder)a % bYesR K::operator %(S b);R operator %(K a, S b);
Increment Prefix++aYesR& K::operator ++();R& operator ++(K& a);
Increment Postfixa++.YesR K::operator ++(int);R operator ++(K& a, int);
Decrement Prefix--aYesR& K::operator --();R& operator --(K& a);
Decrement Postfixa--YesR K::operator --(int);R operator --(K& a, int);

Comparison operators / relational operators

 Operator name SyntaxCan overloadPrototype example as member of KPrototype examples outside class definition
Equal to.a == bYesbool K::operator ==(S const& b) const;bool operator ==(K const& a, S const& b);
Not equal toa != b -or- a not_eq bYesbool K::operator !=(S const& b) const;bool operator !=(K const& a, S const& b);
Greater thana > bYesbool K::operator >(S const& b) const;bool operator >(K const& a, S const& b);
Less thana < bYesbool K::operator <(S const& b) const;bool operator <(K const& a, S const& b);
Greater than or equal toa >= bYesbool K::operator >=(S const& b) const;bool operator >=(K const& a, S const& b);
Less than or equal toa <= bYesbool K::operator <=(S const& b) const;bool operator <=(K const& a, S const& b);

Logical operators

 Operator nameSyntaxCan overloadProtype examples as member of KProtype examples outside class definitions
Logical negation (NOT)!a -or- not aYesbool K::operator !() const;bool operator !(K a);
Logical ANDa && b -or- a and bYesbool K::operator &&(S b) const; bool operator &&(K a, S b);
Logical ORab -or- a or bYes

Bitwise operators

Operator nameSyntaxCan overloadProtype examples as member of KProtype examples outside class definitions
Bitwise NOT~a -or- compl aYesR K::operator ~();R operator ~(K a);
Bitwise ANDa & b -or- a bitand bYes R K::operator &(S b);R operator &(K a, S b);
Bitwise ORan -or- a bitor bYesR K::operator
Bitwise XORa ^ b -r- a xor bYesR K::operator ^(S b);R operator ^(K a, S b);
 Bitwise left shifta << bYesR K::operator <<(S b);R operator <<(K a, S b);
Bitwise right shifta >> bYesR K::operator >>(S b);R operator >>(K a, S b);

Compound assignment operators

Operator nameSyntaxMeaning.Can overloadProtype examples as member of KProtype examples outside class definitions
Addition assignmenta += ba = a + bYesR& K::operator +=(S b);R& operator +=(K& a, S b);
Subtraction assignmenta -= ba = a - bYesR& K::operator -=(S b);R& operator -=(K& a, S b);
 Multiplication assignmenta *= ba = a * bYesR& K::operator *=(S b);R& operator *=(K& a, S b);
Division assignmenta /= ba = a / bYesR& K::operator /=(S b);R& operator /=(K& a, S b);
Modulo assignmenta %= ba = a % bYesR& K::operator %=(S b);R& operator %=(K& a, S b);
Bitwise AND assignmenta &= b -or- a end_eq ba = a & bYesR& K::operator &=(S b);R& operator &=(K& a, S b);
 Bitwise OR assignmenta |= b -or- a or_eq b a = a | bYesR& K::operator |=(S b); R& operator |=(K& a, S b);
 Bitwise XOR assignmenta ^= b -or- a xor_eq b a = a^bYesR& K::operator ^=(S b);R& operator ^=(K& a, S b);
Bitwise left shift assignmenta <<= ba = a << bYesR& K::operator <<=(S b);R& operator <<=(K& a, S b);
Bitwise right shift assignmenta >>= ba = a >> bYesR& K::operator >>=(S b);R& operator >>=(K& a, S b);

Member and pointer operators

Operator nameSyntaxCan overloadProtype examples as member of KProtype examples outside class definitions
Array subsripta[b]YesR& K::operator [](S b);N/A
Indirection ("object pointed to by a")aYesR& K::operator *();R& operator *(K a);
Address ("address of a")&aYesR* K::operator &();R* operator &(K a);
 Structure dereference ("member b of object pointed to by a")a->b YesR* K::operator ->();N/A
Structure reference ("member b of object a")a.bNoN/AN/A
Member pointed to by b of object pointed to by aa->*bYesR& K::operator ->*(S b);R& operator ->*(K a, S b);
Member pointed to by b of object aa.*bNoN/AN/A

Other operators

Operator nameSyntaxCan overloadProtype examples as member of KProtype examples outside class definitions
Function calla(a1, a2) YesR K::operator ()(S a, T b, ...);N/A
Commaa, bYesR K::operator ,(S b); R operator ,(K a, S b);
Ternary conditionala ? b : cNoN/A N/A
Scope resolution a::bNoN/AN/A
User-defined literals"a"_bYesN/AR operator "" _b(T a);
 Size-of sizeof(a) -or- sizeof(type)NoN/AN/A
Size of parameter packsizeof...(args)NoN/AN/A
Align-ofalignof(type) -or- _Alignof(type)NoN/AN/A
Type identificationtypeid(a) -or- typeid(type)NoN/AN/A
Conversion (C-style cast)(type)a -or- type(a)YesK::operator R();N/A
 static_cast conversionstatic_cast\<type>(a)NoN/AN/A
dynamic_cast conversiondynamic_cast\<type>(a)NoN/AN/A
const_cast conversionconst_cast\<type>(a)NoN/AN/A
reinterpret_cast conversionreinterpret_cast\<type>(a)NoN/AN/A
Allocate storagenew typeYesvoid* K::operator new(size_t x);void* operator new(size_t x);
Allocate storage (array)new type[n] Yesvoid* K::operator new[](size_t a); void* operator new[](size_t x);
Deallocate storagedelete a Yesvoid K::operator delete(void* a);void operator delete(void* a);
Deallocate storage (array) delete[] aYesvoid K::operator delete[](void* a);void operator delete[](void* a);
Exception checknoexcept(a)NoN/AN/A

See also